/*
 *  Copyright (c) 2010 Brian Stanek <bstanek@gmail.com>
 *
 *  Permission is hereby granted, free of charge, to any person
 *  obtaining a copy of this software and associated documentation
 *  files (the "Software"), to deal in the Software without
 *  restriction, including without limitation the rights to use,
 *  copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following
 *  conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *  OTHER DEALINGS IN THE SOFTWARE.
 */

package guice.injector
{

import flash.utils.Dictionary;
import guice.Binding;
import guice.Injector;
import guice.Module;
import guice.Key;
import guice.Provider;
import guice.errors.DuplicateBindingError;

public class InjectorImpl implements Injector
{
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    public function InjectorImpl()
    {
        super();
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    private var bindings:Object = {};

    private var parent:Injector;

    //--------------------------------------------------------------------------
    //
    //  Methods: Injector
    //
    //--------------------------------------------------------------------------

    public function createChildInjector(modules:Vector.<Module>):Injector
    {
        var injector:InjectorImpl = new InjectorImpl();
        injector.parent = this;
        // need to handle the modules
        return injector;
    }

    public function findBindingsByType(type:Class):Vector.<Binding>
    {
        return new Vector.<Binding>();
    }

    public function getAllBindings():Dictionary
    {
        return new Dictionary();
    }

    public function getBindings():Dictionary
    {
        return new Dictionary();
    }

    public function getBindingForType(type:Class):Binding
    {
        return null;
    }

    public function getBindingForKey(key:Key):Binding
    {
        return null;
    }

    public function getInstanceForType(type:Class):*
    {
        return getInstanceForKey(new Key(type));
    }

    public function getInstanceForKey(key:Key):*
    {
        var binding:Binding = findBindingForKey(key);
        if (binding)
            return binding.getProvider().get();
        if (key.getAnnotation())
            throw new Error("No binding for type/annotation");
        return create(key.getType());
    }

    public function getParent():Injector
    {
        return parent;
    }

    public function getProviderForType(type:Class):Provider
    {
        return null;
    }

    public function getProviderForKey(key:Key):Provider
    {
        return null;
    }

    public function getScopeBindings():Dictionary
    {
        return new Dictionary();
    }

    public function injectMembers(instance:Object):void
    {
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    public function create(cls:Class):*
    {
        var instance:* = new cls();
        // inject instance members here
        return instance;
    }

    public function addBinding(binding:Binding):void
    {
        var hash:String = binding.getKey().getHashCode();
        if (bindings[hash])
            throw new DuplicateBindingError(binding.getKey());
        bindings[hash] = binding;
    }

    public function findBindingForKey(key:Key):Binding
    {
        return bindings[key.getHashCode()];
    }

}

}
